#include <iostream>
#include <fstream>
#include <string.h>
#include <vector>
#include <set>
#include <algorithm>
#include "distTree.h"

struct ask
{
    std::string text;
    int priority;

    ask()
    {
        text.clear();
        priority = 0;
    }
    ask(std::string &newText)
    {
        text = newText;
        priority = 1;
    }

    bool operator==(const ask& other)
    {
        return (text == other.text);
    }
    bool operator!=(const ask& other)
    {
        return !(*this == other);
    }
    ask operator+(const ask& other) //Только чтобы работало мое distTree
    {
        priority += other.priority;
        text += other.text;
        return *this;
    }

};

/*bool strLess(const ask& first, const ask& second)
{
    //size_t len = std::min(first.text.length(), second.text.length());
    //return first.text.substr(0, len) < second.text.substr(0, len);
    return first.text < second.text;
}
bool priorLess(const ask& first, const ask& second)
{
    return first.priority < second.priority;
}*/
struct strLess
{
    bool operator()(const ask& x, const ask& y) const
    {
        return x.text < y.text;
    }

};
struct priorGreat
{
    bool operator()(const ask& x, const ask& y) const
    {
        return x.priority > y.priority;
    }

};

ask searchNewMax(distTree<ask, priorGreat> &base, size_t begin, size_t end, const std::set<ask, priorGreat> &top)
{
    if (top.find(base.getMin(begin, end)) != top.end())
    {
        if (end == begin + 1)
            return ask();
        return std::min(searchNewMax(base, begin, begin + (end - begin)/2, top),
                            searchNewMax(base, begin + (end - begin)/2, end, top), priorGreat());
    }
    else
        return base.getMin(begin, end);
}

bool getStats(std::vector<ask> &base, const char* statfile = "askstat.txt")
{
    std::ifstream fin(statfile);
    if (!fin.is_open())
        return false;

    size_t askCount = 0;
    fin >> askCount;
    base.resize(askCount);
    for (size_t i = 0; i < askCount; ++i)
        fin >> base[i].text >> base[i].priority;
    fin.close();
    std::sort(base.begin(), base.end(), strLess());
    return true;
}
int main()
{
    std::vector<ask> askBase;
    getStats(askBase);

    int suggestCount = 3;

    distTree<ask, priorGreat> askTree(askBase);
    std::cout << "urka!\n";
    askBase.clear();
    std::string newAsk = "/help";
    while (newAsk != "/exit")
    {
        if (newAsk == "/all")
        {
            for (size_t i = 0; i < askTree.sizeArr(); ++i)
                std::cout << askTree[i].text << " (" << askTree[i].priority << ")\n";
            std::cout << "---------------------\n";
        }
        else if (newAsk == "/help")
        {
            std::cout << "all, exit, help\n";
        }
        else if (newAsk[0] != '/')
        {
            std::cout << "_______search...______\n";
            size_t upBorder = std::lower_bound(askTree.beginArr(), askTree.endArr(), ask(newAsk), strLess())
                            - askTree.beginArr();

            newAsk[newAsk.length() - 1] = newAsk[newAsk.length() - 1] + 1;
            size_t downBorder = std::lower_bound(askTree.beginArr(), askTree.endArr(), ask(newAsk), strLess())
                            - askTree.beginArr();
            newAsk[newAsk.length() - 1] = newAsk[newAsk.length() - 1] - 1;
            //std::cout << upBorder << " " << downBorder << "\n";
            if (upBorder >= 0 && downBorder > upBorder && downBorder <= askTree.sizeArr())
            {
                for (size_t i = upBorder; i < downBorder; ++i)
                    std::cout << askTree[i].text << " (" <<
                                askTree[i].priority << ")\n";
                std::cout << "   ---MAX:---\n";
                std::set<ask, priorGreat> top;
                size_t left = upBorder;
                size_t right = downBorder;
                while (top.size() < std::min(suggestCount, (int)(downBorder - upBorder)))
                {
                    top.insert(searchNewMax(askTree, upBorder, downBorder, top));
                }
                for (std::set<ask, priorGreat>::iterator i = top.begin(); i != top.end(); ++i)
                {
                    std::cout << (*i).text << " (" << (*i).priority << ")\n";
                }
            }
            else
                std::cout << "<nothing to suggest>\n";

            std::cout << "----------------------\n";
        }
        else
            std::cout << "Command not found.\n";
        std::cin >> newAsk;
    }

    //saveStats(askBase);
    return 0;
}
